package com.streamkar.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @ClassName EsUtil
 * @Description
 * @Author tyfrost
 * @Date 2018/11/19 4:53 PM
 * @Version 1.0
 */
@Component
public class EsUtil {
    private static final Logger LOGGER = LoggerFactory.getLogger(EsUtil.class);

    public String bulidMustDsl(String dsl, Map<String, Object> paramMap) {
        if (CollectionUtils.isEmpty(paramMap) || StringUtils.isBlank(dsl)) {
            LOGGER.info("bulidMustDsl but paramMap is empty or dsl is empty");
            return dsl;
        }
        LOGGER.info("bulidMustDsl paramMap is {},dsl:{}", Jsons.instance().toJson(paramMap), dsl);

        // 解析DSL
        JSONObject jsonObject = JSON.parseObject(dsl);
        // 获取Bool节点
        JSONObject boolObject = jsonObject.getJSONObject("query").getJSONObject("bool");
        List<JSONObject> queryList = (List<JSONObject>) boolObject.get("must");
        if (CollectionUtils.isEmpty(queryList)) {
            queryList = new ArrayList<>();
            boolObject.put("must", queryList);
        }

        for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
            queryList.add(mustNode(entry.getKey(), entry.getValue()));
        }
        dsl = jsonObject.toJSONString();
        LOGGER.info("build must dsl result:{}", dsl);
        return dsl;
    }

    public String bulidDsl(String dsl) {
        if (StringUtils.isBlank(dsl)) {
            LOGGER.info("bulidDsl but dsl is empty");
            return dsl;
        }
        // 解析DSL
        JSONObject jsonObject = JSON.parseObject(dsl);
        // 获取Bool节点
        JSONObject boolObject = jsonObject.getJSONObject("query").getJSONObject("bool");
        boolObject.put("minimum_should_match", 1);
        dsl = jsonObject.toJSONString();
        LOGGER.info("bulidDsl result:{}", dsl);
        return dsl;
    }

    public String bulidShouldDsl(String dsl, Map<String, Object> paramMap) {
        if (CollectionUtils.isEmpty(paramMap) || StringUtils.isBlank(dsl)) {
            LOGGER.info("bulidShouldDsl but paramMap is empty or dls is empty");
            return dsl;
        }
        LOGGER.info("bulidShouldDsl paramMap is {},dsl:{}", Jsons.instance().toJson(paramMap), dsl);

        // 解析DSL
        JSONObject jsonObject = JSON.parseObject(dsl);
        // 获取Bool节点
        JSONObject boolObject = jsonObject.getJSONObject("query").getJSONObject("bool");
        List<JSONObject> queryList = (List<JSONObject>) boolObject.get("should");
        if (CollectionUtils.isEmpty(queryList)) {
            queryList = new ArrayList<>();
            boolObject.put("should", queryList);
        }

        for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
            queryList.add(shouldNode(entry.getKey(), entry.getValue()));
        }
        dsl = jsonObject.toJSONString();
        LOGGER.info("build should dsl result:{}", dsl);
        return dsl;
    }

    private JSONObject mustNode(String key, Object value) {
        String nodeFormat = "";
        if (value instanceof String) {
            nodeFormat = "{\"term\": {\"" + key.trim() + ".keyword\": \"" + String.valueOf(value).trim() + "\"}}";
        } else if (value instanceof List) {
            List<String> paramValueList = (List<String>) value;
            String paramValueString = "";
            for (int i = 0; i < paramValueList.size(); i++) {
                paramValueString += "\"" + paramValueList.get(i).trim() + "\"";
                if (i < paramValueList.size() - 1) {
                    paramValueString += ',';
                }
            }
            nodeFormat = "{\"terms\": {\"" + key.trim() + ".keyword\": [" + paramValueString + "]}}";
        } else if (value instanceof Integer) {
            nodeFormat = "{\"term\": {\"" + key.trim() + "\":" + value + "}}";
        } else if (value instanceof Boolean) {
            nodeFormat = "{\"term\": {\"" + key.trim() + "\":" + value + "}}";
        } else {
            LOGGER.info("build dsl node return,can not match the param type,the key is:{},value is:{}", key, value);
        }

        return JSON.parseObject(nodeFormat);
    }

    private JSONObject shouldNode(String key, Object value) {
        String nodeFormat = "";
        if (value instanceof String) {
            nodeFormat = "{\"wildcard\": {\"" + key.trim() + "\": \"*" + String.valueOf(value).trim() + "*\"}}";
        } else if (value instanceof Integer) {
            nodeFormat = "{\"term\": {\"" + key.trim() + "\":" + value + "}}";
        } else {
            LOGGER.info("build dsl node return,can not match the param type,the key is:{},value is:{}", key, value);
        }

        return JSON.parseObject(nodeFormat);
    }

    public boolean belongCalendar(Date time, String from, String to) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date fromDate = sdf.parse(from);
        Date endDate = sdf.parse(to);
        Calendar date = Calendar.getInstance();
        date.setTime(time);

        Calendar after = Calendar.getInstance();
        after.setTime(fromDate);

        Calendar before = Calendar.getInstance();
        before.setTime(endDate);

        if (date.after(after) && date.before(before)) {
            return true;
        } else {
            return false;
        }
    }
}
